package com.recSys.controller;

import com.recSys.dataPrediction.Predict4Ceme;
import com.recSys.dataPrediction.Predict4Fun;
import com.recSys.dataProcessing.Deal4RecFun;
import com.recSys.inter.*;
import com.recSys.model.*;
import com.recSys.util.*;
import net.sf.json.JSONException;
import net.sf.json.JSONObject;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Transformer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.*;


@Controller
@RequestMapping("/funeralProcess")
public class FBPEventNodeController {

    private static final int BodyPickUp_SERVICETYPE_ID = 15;
    private static final int BodyStorage_SERVICETYPE_ID = 16;
    private static final int FuneralParlor_ORGTYPE_ID = 5;
    private static final int Cemetery_ORGTYPE_ID = 6;
    private static final int CemeteryPark_ORGTYPE_ID = 13;
    private static final int OfferService3_ORGTYPE_ID = 9;

    @Autowired
    BusiProcBaseInfoMapper bpBaseInfoMapper;
    @Autowired
    UserFeedBackInfoMapper userFeedBackInfoMapper;
    @Autowired
    RecResultMapper recResultMapper;
    @Autowired
    UserMapper userMapper;
    @Autowired
    OrganizationMapper organizationMapper;
    @Autowired
    AreaCodeMapper areaCodeMapper;
    @Autowired
    FamilyCommunityMapper familyCommunityMapper;
    @Autowired
    FamilyCommunityMemberMapper familyCommunityMemberMapper;
    @Autowired
    ServiceMapper serviceMapper;
    @Autowired
    ProductMapper productMapper;
    @Autowired
    BuyRecordMapper buyRecordMapper;
    @Autowired
    DeadInfoMapper deadInfoMapper;
    @Autowired
    ProductCatalogueMapper productCatalogueMapper;

    /**
     * 推荐殡仪馆（流程状态 < 3 时 使用）
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "/recFuneralParlor", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> recFuneralParlor(HttpServletRequest request) {
        try {
            String jsonStr = JsonHandler.readJsonFromRequest(request);
            JSONObject obj = JSONObject.fromObject(jsonStr);
            Map<String, Object> isLogin = OAuthHandler.ApiValidateUserLogin(obj);
            if (isLogin.containsKey("errorcode"))
                return JsonHandler.writeJsontoResponse((int) isLogin.get("errorcode"), "");
            User tempU = (User) isLogin.get("user");
            User user = userMapper.selectByPrimaryKey(tempU.getId());
            List<Organization> candidateOrgList = new ArrayList<>();

            //根据逝者信息，利用L2R_L2LOSS_SVC_DUAL模型，预测用户最需要去的殡仪馆
            int bpID = obj.getInt("bpID");
            BusiProcBaseInfo bpbi = bpBaseInfoMapper.selectByPrimaryKey(bpID);
            double prediction = Predict4Fun.predict(user, bpbi);
            if(prediction != -1.0) {
                String[] arr = Deal4RecFun.orgSet.toArray(new String[0]);
                String orgCode = arr[(int) (prediction)];
                Organization mainOrg = organizationMapper.selectByOrgCode(orgCode);
                candidateOrgList.add(mainOrg);
            } else {
                return JsonHandler.writeJsontoResponse(7004, "");
            }


            //获取用户当前位置附近殡仪馆
            double longitude = obj.getDouble("longitude");
            double latitude = obj.getDouble("latitude");
            List<Organization> nearByList = searchNearbyOrgs(longitude, latitude, FuneralParlor_ORGTYPE_ID, 30);
            if(nearByList != null && nearByList.size() !=0) {
                for (Organization o : nearByList) {
                    if (!candidateOrgList.contains(o) && candidateOrgList.size() < 3) candidateOrgList.add(o);
                }
            }

            //获取逝者、用户及用户家族成员身份信息--籍贯 周围的殡仪馆
            String cPos = user.getIDCard().substring(0, 6);
            String dPos = bpbi.getDeadIDNumber().substring(0, 6);
            List<String> areaCodes = new ArrayList<>();
            areaCodes.add(cPos);
            if (!areaCodes.contains(dPos)) areaCodes.add(dPos);
            List<User> memberList = new ArrayList<>();
            List<FamilyCommunity> fcs = familyCommunityMapper.selectByUserId(user.getId());
            for (FamilyCommunity fc : fcs) {
                memberList.addAll(familyCommunityMemberMapper.selectByCommId(fc.getId()));
            }
            GeneralHandler.removeDuplicate(memberList);
            for (User u : memberList) {
                String areaCode = u.getIDCard().substring(0, 6);
                if (!areaCodes.contains(areaCode)) areaCodes.add(areaCode);
            }

            for (String areaCode : areaCodes) {
                AreaCode ac = areaCodeMapper.selectByPrimaryKey(areaCode);
                System.out.println(ac.getAddrContent());
                String jsonString = HttpClientHandler.doGet(ac.getAddrContent());
                System.out.println(jsonString);
                JSONObject location = JSONObject.fromObject(jsonString).getJSONObject("result").getJSONObject("location");
                double lng = location.getDouble("lng");
                double lat = location.getDouble("lat");
                List<Organization> others = searchNearbyOrgs(lng, lat, FuneralParlor_ORGTYPE_ID, 30);
                if(others != null && others.size() != 0) {
                    for (Organization o : others) {
                        if (!candidateOrgList.contains(o)) candidateOrgList.add(o);
                    }
                }
            }

            //保存返回结果
            StringBuilder result = new StringBuilder();
            for (Organization o : candidateOrgList) {
                result.append(o.getId()).append(" ");
            }
            RecResult recResult = recResultMapper.selectByEventNode(bpID, 1);
            if (recResult == null) {
                recResult = new RecResult();
                recResult.setBpID(bpID);
                recResult.setItemType(1);//1：殡仪馆
                recResult.setItemIDs(result.toString());
                recResult.setState(1);
                recResult.setAddTime(new Date());
                recResultMapper.insertSelective(recResult);
            } else {
                recResult.setItemIDs(result.toString());
                recResult.setState(1);
                recResult.setAddTime(new Date());
                recResultMapper.updateByPrimaryKeySelective(recResult);
            }

            //TODO 加速返回结果时间
//            // 读取根据用户行为使用ItemKNN得到的推荐列表
//            String fileName = "/com/recSys/config/offlineTaskOutput.properties";
//            String inputPath = new FileHandler().readConfig(fileName,"recommendOrgListByItemKNNPath");
//            List<RecommendedItem> recommendedItemList = new FileHandler().readRecommendList(inputPath,user.getId());
//
//            //将推荐列表的殡仪馆添加到候选列表
//            for (RecommendedItem ri:
//                    recommendedItemList) {
//                Organization o = organizationMapper.selectByPrimaryKey(Integer.valueOf(ri.getItemId()));
//                if(o != null)
//                    candidateOrgList.add(o);
//            }
//            GeneralHandler.removeDuplicate(candidateOrgList);
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("candidateOrgList", candidateOrgList);
            resultMap.put("prefix", FileHandler.TREAL_STORE_PREFIX);
            return JsonHandler.writeJsontoResponse(7000, resultMap);
        } catch (JSONException e) {
            e.printStackTrace();
            LogRecord.ERROR.error(e.toString());
            return JsonHandler.writeJsontoResponse(7003, "");
        } catch (Exception e) {
            e.printStackTrace();
            LogRecord.ERROR.error(e.toString());
            return JsonHandler.writeJsontoResponse(7001, "");
        }
    }

    /**
     * 获取推荐殡仪馆结果（流程状态 >= 3 时 使用）
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "/getRecFuneralParlorResult", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> getRecFuneralParlorResult(HttpServletRequest request) {
        try {
            String jsonStr = JsonHandler.readJsonFromRequest(request);
            JSONObject obj = JSONObject.fromObject(jsonStr);
            Map<String, Object> isLogin = OAuthHandler.ApiValidateUserLogin(obj);
            if (isLogin.containsKey("errorcode"))
                return JsonHandler.writeJsontoResponse((int) isLogin.get("errorcode"), "");
            int bpID = obj.getInt("bpID");
            int itemType = obj.getInt("itemType");
            String result = recResultMapper.selectByEventNode(bpID, itemType).getItemIDs();
            String[] orgIDList = result.split(" ");
            List<Organization> candidateOrgList = new ArrayList<>();
            for (String orgID : orgIDList) {
                candidateOrgList.add(organizationMapper.selectByPrimaryKey(Integer.valueOf(orgID)));
            }
            List<UserFeedBackInfo> adopted = userFeedBackInfoMapper.selectByEventNode(bpID, 1, 2);
            List<Integer> adoptedList = new ArrayList<>();
            for (UserFeedBackInfo fd : adopted) {
                adoptedList.add(fd.getItemID());
            }
            List<UserFeedBackInfo> unrelated = userFeedBackInfoMapper.selectByEventNode(bpID, 1, 3);
            List<Integer> unrelatedList = new ArrayList<>();
            for (UserFeedBackInfo fd : unrelated) {
                unrelatedList.add(fd.getItemID());
            }

            Map<String, Object> resultMap = new HashMap();
            resultMap.put("candidateOrgList", candidateOrgList);
            resultMap.put("adoptedList", adoptedList);
            resultMap.put("unrelatedList", unrelatedList);
            resultMap.put("prefix", FileHandler.TREAL_STORE_PREFIX);
            return JsonHandler.writeJsontoResponse(7000, resultMap);
        } catch (JSONException e) {
            e.printStackTrace();
            LogRecord.ERROR.error(e.toString());
            return JsonHandler.writeJsontoResponse(7003, "");
        } catch (Exception e) {
            e.printStackTrace();
            LogRecord.ERROR.error(e.toString());
            return JsonHandler.writeJsontoResponse(7001, "");
        }
    }

    /**
     * 推荐遗体接送服务（流程状态 < 4 时 使用）
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "/recBodyPickupService", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> recBodyPickupService(HttpServletRequest request) {
        try {
            String jsonStr = JsonHandler.readJsonFromRequest(request);
            JSONObject obj = JSONObject.fromObject(jsonStr);
            Map<String, Object> isLogin = OAuthHandler.ApiValidateUserLogin(obj);
            if (isLogin.containsKey("errorcode"))
                return JsonHandler.writeJsontoResponse((int) isLogin.get("errorcode"), "");
            int bpID = obj.getInt("bpID");
            BusiProcBaseInfo bpInfo = bpBaseInfoMapper.selectByPrimaryKey(bpID);
            //获取用户对殡仪馆的选择操作结果
            List<Integer> orgIDs = getRecFunResult(bpInfo);

            //按序获取该殡仪馆列表中殡仪馆提供的接送遗体服务 先排惠民政策 再按评分高低
            List<ServiceInfo> mayNeedServiceList = new ArrayList<>();
            Map<String, Object> paraMap = new HashMap<>();
            paraMap.put("servTypeID", BodyPickUp_SERVICETYPE_ID);
            paraMap.put("hmType", "%" + bpInfo.getDeadHMPolicyType() + "%");
            System.out.println(orgIDs.size());
            if (orgIDs.size() >= 4) {
                paraMap.put("limit", 2);
            } else if (orgIDs.size() == 3) {
                paraMap.put("limit", 3);
            } else if (orgIDs.size() == 2) {
                paraMap.put("limit", 4);
            } else {
                paraMap.put("limit", 6);
            }
            for (Integer orgID : orgIDs) {
                paraMap.put("orgID", orgID);
                mayNeedServiceList.addAll(serviceMapper.selectByOrgIDAndType(paraMap));
            }

            //获取上面殡仪馆列表中殡仪馆周围的第三方服务提供商 6个 及其服务列表
            List<Organization> offerServiceOrgList = getNearByOrgsByType(orgIDs, OfferService3_ORGTYPE_ID,15);
            List<ServiceInfo> offer3ServiceList = new ArrayList<>();
            if (offerServiceOrgList != null && offerServiceOrgList.size() != 0) {
                for (Organization org : offerServiceOrgList) {
                    paraMap.put("orgID", org.getId());
                    offer3ServiceList.addAll(serviceMapper.selectByOrgIDAndType(paraMap));
                }
            }

            //根据服务预约次数降序排序返回
            for (ServiceInfo s : offer3ServiceList) {
                s.setBookTimes(serviceMapper.getServiceBookTimes(s.getId()));
            }
            Collections.sort(offer3ServiceList);

            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("mayNeedServiceList", mayNeedServiceList);
            resultMap.put("offer3ServiceList", offer3ServiceList);
            resultMap.put("prefix", FileHandler.TREAL_STORE_PREFIX);

            //保存返回结果
            StringBuilder result = new StringBuilder();
            result.append("mayNeedServiceList ");
            for (ServiceInfo o : mayNeedServiceList) {
                result.append(o.getId()).append(" ");
            }
            result.append("!offer3ServiceList ");
            for (ServiceInfo o : offer3ServiceList) {
                result.append(o.getId()).append(" ");
            }
            RecResult recResult = recResultMapper.selectByEventNode(bpID, 2);
            if (recResult == null) {
                recResult = new RecResult();
                recResult.setBpID(bpID);
                recResult.setItemType(2);//2：遗体运送服务
                recResult.setItemIDs(result.toString());
                recResult.setState(1);
                recResult.setAddTime(new Date());
                recResultMapper.insertSelective(recResult);
            } else {
                recResult.setItemIDs(result.toString());
                recResult.setState(1);
                recResult.setAddTime(new Date());
                recResultMapper.updateByPrimaryKeySelective(recResult);
            }
            return JsonHandler.writeJsontoResponse(7000, resultMap);
        } catch (JSONException e) {
            e.printStackTrace();
            LogRecord.ERROR.error(e.toString());
            return JsonHandler.writeJsontoResponse(7003, "");
        } catch (Exception e) {
            e.printStackTrace();
            LogRecord.ERROR.error(e.toString());
            return JsonHandler.writeJsontoResponse(7001, "");
        }
    }

    /**
     * 获取推荐遗体接送服务结果（流程状态 >= 4 时 使用）
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "/getRecBodyPickupServiceList", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> getRecBodyPickupServiceList(HttpServletRequest request) {
        try {
            String jsonStr = JsonHandler.readJsonFromRequest(request);
            JSONObject obj = JSONObject.fromObject(jsonStr);
            Map<String, Object> isLogin = OAuthHandler.ApiValidateUserLogin(obj);
            if (isLogin.containsKey("errorcode"))
                return JsonHandler.writeJsontoResponse((int) isLogin.get("errorcode"), "");
            int bpID = obj.getInt("bpID");
            int itemType = obj.getInt("itemType");
            String result = recResultMapper.selectByEventNode(bpID, itemType).getItemIDs();
            String[] kinds = result.split("!");
            String[] mayNeedServiceIDList = kinds[0].split(" ");
            String[] offer3ServiceIDList = kinds[1].split(" ");
            List<ServiceInfo> mayNeedServiceList = new ArrayList<>();
            for (int i = 1; i < mayNeedServiceIDList.length; i++) {
                mayNeedServiceList.add(serviceMapper.selectByID(Integer.valueOf(mayNeedServiceIDList[i])));
            }
            List<ServiceInfo> offer3ServiceList = new ArrayList<>();
            for (int i = 1; i < offer3ServiceIDList.length; i++) {
                offer3ServiceList.add(serviceMapper.selectByID(Integer.valueOf(offer3ServiceIDList[i])));
            }
            List<UserFeedBackInfo> adopted = userFeedBackInfoMapper.selectByEventNode(bpID, 2, 2);
            List<Integer> adoptedList = new ArrayList<>();
            for (UserFeedBackInfo fd : adopted) {
                adoptedList.add(fd.getItemID());
            }
            List<UserFeedBackInfo> unrelated = userFeedBackInfoMapper.selectByEventNode(bpID, 2, 3);
            List<Integer> unrelatedList = new ArrayList<>();
            for (UserFeedBackInfo fd : unrelated) {
                unrelatedList.add(fd.getItemID());
            }
            Map<String, Object> resultMap = new HashMap();
            resultMap.put("mayNeedServiceList", mayNeedServiceList);
            resultMap.put("offer3ServiceList", offer3ServiceList);
            resultMap.put("adoptedList", adoptedList);
            resultMap.put("unrelatedList", unrelatedList);
            resultMap.put("prefix", FileHandler.TREAL_STORE_PREFIX);
            return JsonHandler.writeJsontoResponse(7000, resultMap);
        } catch (JSONException e) {
            e.printStackTrace();
            LogRecord.ERROR.error(e.toString());
            return JsonHandler.writeJsontoResponse(7003, "");
        } catch (Exception e) {
            e.printStackTrace();
            LogRecord.ERROR.error(e.toString());
            return JsonHandler.writeJsontoResponse(7001, "");
        }
    }


    /**
     * 推荐遗体寄存服务（流程状态 < 6 时 使用）
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "/recBodyStorageService", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> recBodyStorageService(HttpServletRequest request) {
        try {
            String jsonStr = JsonHandler.readJsonFromRequest(request);
            JSONObject obj = JSONObject.fromObject(jsonStr);
            Map<String, Object> isLogin = OAuthHandler.ApiValidateUserLogin(obj);
            if (isLogin.containsKey("errorcode"))
                return JsonHandler.writeJsontoResponse((int) isLogin.get("errorcode"), "");
            int bpID = obj.getInt("bpID");
            BusiProcBaseInfo bpInfo = bpBaseInfoMapper.selectByPrimaryKey(bpID);
            //获取用户对殡仪馆的选择操作结果
            List<Integer> orgIDs = getRecFunResult(bpInfo);

            //按序获取该殡仪馆列表中殡仪馆提供的遗体寄存服务 先排惠民政策 再按评分高低
            List<ServiceInfo> mayNeedServiceList = new ArrayList<>();
            Map<String, Object> paraMap = new HashMap<>();
            paraMap.put("servTypeID", BodyStorage_SERVICETYPE_ID);
            paraMap.put("hmType", "%" + bpInfo.getDeadHMPolicyType() + "%");
            if (orgIDs.size() >= 4) {
                paraMap.put("limit", 2);
            } else if (orgIDs.size() == 3) {
                paraMap.put("limit", 3);
            } else if (orgIDs.size() == 2) {
                paraMap.put("limit", 4);
            } else {
                paraMap.put("limit", 6);
            }
            for (Integer orgID : orgIDs) {
                paraMap.put("orgID", orgID);
                mayNeedServiceList.addAll(serviceMapper.selectByOrgIDAndType(paraMap));
            }

            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("mayNeedServiceList", mayNeedServiceList);
            resultMap.put("prefix", FileHandler.TREAL_STORE_PREFIX);

            //保存返回结果
            StringBuilder result = new StringBuilder();
            result.append("mayNeedServiceList ");
            for (ServiceInfo o : mayNeedServiceList) {
                result.append(o.getId()).append(" ");
            }
            RecResult recResult = recResultMapper.selectByEventNode(bpID, 3);
            if (recResult == null) {
                recResult = new RecResult();
                recResult.setBpID(bpID);
                recResult.setItemType(3);//3：遗体寄存服务
                recResult.setItemIDs(result.toString());
                recResult.setState(1);
                recResult.setAddTime(new Date());
                recResultMapper.insertSelective(recResult);
            } else {
                recResult.setItemIDs(result.toString());
                recResult.setState(1);
                recResult.setAddTime(new Date());
                recResultMapper.updateByPrimaryKeySelective(recResult);
            }
            return JsonHandler.writeJsontoResponse(7000, resultMap);
        } catch (JSONException e) {
            e.printStackTrace();
            LogRecord.ERROR.error(e.toString());
            return JsonHandler.writeJsontoResponse(7003, "");
        } catch (Exception e) {
            e.printStackTrace();
            LogRecord.ERROR.error(e.toString());
            return JsonHandler.writeJsontoResponse(7001, "");
        }
    }


    /**
     * 获取推荐遗体寄存服务结果（流程状态 >= 6 时 使用）
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "/getRecBodyStorageServiceList", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> getRecBodyStorageServiceList(HttpServletRequest request) {
        try {
            String jsonStr = JsonHandler.readJsonFromRequest(request);
            JSONObject obj = JSONObject.fromObject(jsonStr);
            Map<String, Object> isLogin = OAuthHandler.ApiValidateUserLogin(obj);
            if (isLogin.containsKey("errorcode"))
                return JsonHandler.writeJsontoResponse((int) isLogin.get("errorcode"), "");
            int bpID = obj.getInt("bpID");
            int itemType = obj.getInt("itemType");
            String result = recResultMapper.selectByEventNode(bpID, itemType).getItemIDs();
            String[] mayNeedServiceIDList = result.split(" ");
            List<ServiceInfo> mayNeedServiceList = new ArrayList<>();
            for (int i = 1; i < mayNeedServiceIDList.length; i++) {
                mayNeedServiceList.add(serviceMapper.selectByID(Integer.valueOf(mayNeedServiceIDList[i])));
            }
            List<UserFeedBackInfo> adopted = userFeedBackInfoMapper.selectByEventNode(bpID, 3, 2);
            List<Integer> adoptedList = new ArrayList<>();
            for (UserFeedBackInfo fd : adopted) {
                adoptedList.add(fd.getItemID());
            }
            List<UserFeedBackInfo> unrelated = userFeedBackInfoMapper.selectByEventNode(bpID, 3, 3);
            List<Integer> unrelatedList = new ArrayList<>();
            for (UserFeedBackInfo fd : unrelated) {
                unrelatedList.add(fd.getItemID());
            }
            Map<String, Object> resultMap = new HashMap();
            resultMap.put("mayNeedServiceList", mayNeedServiceList);
            resultMap.put("adoptedList", adoptedList);
            resultMap.put("unrelatedList", unrelatedList);
            resultMap.put("prefix", FileHandler.TREAL_STORE_PREFIX);
            return JsonHandler.writeJsontoResponse(7000, resultMap);
        } catch (JSONException e) {
            e.printStackTrace();
            LogRecord.ERROR.error(e.toString());
            return JsonHandler.writeJsontoResponse(7003, "");
        } catch (Exception e) {
            e.printStackTrace();
            LogRecord.ERROR.error(e.toString());
            return JsonHandler.writeJsontoResponse(7001, "");
        }
    }

    /**
     * 推荐寿衣、帽（展示在遗体整容旁，流程状态 < 6 时使用）
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "/recCerements", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> recCerements(HttpServletRequest request) {
        try {
            String jsonStr = JsonHandler.readJsonFromRequest(request);
            JSONObject obj = JSONObject.fromObject(jsonStr);
            Map<String,Object> isLogin = OAuthHandler.ApiValidateUserLogin(obj);
            if(isLogin.containsKey("errorcode"))
                return JsonHandler.writeJsontoResponse((int)isLogin.get("errorcode"), "");
            int bpID = obj.getInt("bpID");
            BusiProcBaseInfo bpInfo = bpBaseInfoMapper.selectByPrimaryKey(bpID);
            String d_IDCard = bpInfo.getDeadIDNumber();//确认逝者性别 不同性别推荐寿衣时有所区别
            int d_sex = 2;
            if( (d_IDCard.charAt(16) - '0') % 2 != 0)
                d_sex = 1;
            //在冷启动情况下，根据逝者属性获取相似逝者情况
            List<String> inputDeadIDs = Arrays.asList(bpInfo.getSimilarDeadInfoIDs().split(" "));
            List<Integer> deadIDList = new ArrayList<>();
            for (String inputDeadID:inputDeadIDs) {
                int deadID = Integer.valueOf(inputDeadID);
                DeadInfo di = deadInfoMapper.selectByPrimaryKey(deadID);
                if(di.getD_sex() == d_sex)
                    deadIDList.add(deadID);
            }
            //获取这些用户购买过的寿衣、帽
            List<Integer> cerementTypeList = new ArrayList<>();
            if(d_sex == 1) {
            	List<Integer> maleCerementIDList = productCatalogueMapper.selectSonCatalogID(19);
            	cerementTypeList.addAll(maleCerementIDList);
            } else if(d_sex == 2) {
            	List<Integer> femaleCerementIDList = productCatalogueMapper.selectSonCatalogID(20);
            	cerementTypeList.addAll(femaleCerementIDList);
            }
            cerementTypeList.addAll(productCatalogueMapper.selectSonCatalogID(30));
            List<Integer> cerementIDList = buyRecordMapper.selectByDeadIDItemType(deadIDList, cerementTypeList);
            List<Integer> capTypeList = new ArrayList<>();
            capTypeList.add(16);
            List<Integer> capIDList = buyRecordMapper.selectByDeadIDItemType(deadIDList,capTypeList);
            List<Product> cerements = productMapper.selectByIDList(cerementIDList);
            List<Product> caps = productMapper.selectByIDList(capIDList);
            //TODO 若有用户在其他平台行为沉淀，用协同过滤

            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("cerementList", cerements.subList(0, cerements.size() > 6 ? 6 : cerements.size()));
            resultMap.put("capList", caps.subList(0, caps.size() > 2 ? 2 : caps.size()));
            resultMap.put("prefix", FileHandler.TREAL_STORE_PREFIX);

            //保存返回结果
            StringBuilder result = new StringBuilder();
            result.append("cerementList ");
            for (Product o : cerements.subList(0, cerements.size() > 6 ? 6 : cerements.size())) {
                result.append(o.getId()).append(" ");
            }
            result.append("!capList ");
            for (Product o : caps.subList(0, caps.size() > 2 ? 2 : caps.size())) {
                result.append(o.getId()).append(" ");
            }
            RecResult recResult = recResultMapper.selectByEventNode(bpID, 4);
            if (recResult == null) {
                recResult = new RecResult();
                recResult.setBpID(bpID);
                recResult.setItemType(4);//4：寿衣、帽
                recResult.setItemIDs(result.toString());
                recResult.setState(1);
                recResult.setAddTime(new Date());
                recResultMapper.insertSelective(recResult);
            } else {
                recResult.setItemIDs(result.toString());
                recResult.setState(1);
                recResult.setAddTime(new Date());
                recResultMapper.updateByPrimaryKeySelective(recResult);
            }
            return JsonHandler.writeJsontoResponse(7000, resultMap);
        } catch (JSONException e) {
            e.printStackTrace();
            LogRecord.ERROR.error(e.toString());
            return JsonHandler.writeJsontoResponse(7003, "");
        } catch (Exception e) {
            e.printStackTrace();
            LogRecord.ERROR.error(e.toString());
            return JsonHandler.writeJsontoResponse(7001, "");
        }
    }


    /**
     * 获取推荐寿衣、帽结果（流程状态 >= 6 时 使用）
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "/getRecCerements", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> getRecCerements(HttpServletRequest request) {
        try {
            String jsonStr = JsonHandler.readJsonFromRequest(request);
            JSONObject obj = JSONObject.fromObject(jsonStr);
            Map<String, Object> isLogin = OAuthHandler.ApiValidateUserLogin(obj);
            if (isLogin.containsKey("errorcode"))
                return JsonHandler.writeJsontoResponse((int) isLogin.get("errorcode"), "");
            int bpID = obj.getInt("bpID");
            int itemType = obj.getInt("itemType");
            String result = recResultMapper.selectByEventNode(bpID, itemType).getItemIDs();
            String[] kinds = result.split("!");
            List<String> inputCerementIDs = new ArrayList<>(Arrays.asList(kinds[0].split(" ")));
            inputCerementIDs.remove(0);
            List<Integer> cerementIDList = new ArrayList<>();
            CollectionUtils.collect(inputCerementIDs, new Transformer() {
                @Override
                public Object transform(Object o) {
                    return Integer.valueOf(o.toString());
                }
            }, cerementIDList);
            List<Product> cerementList = productMapper.selectByIDList(cerementIDList);

            List<String> inputCapIDs = new ArrayList<>(Arrays.asList(kinds[1].split(" ")));
            inputCapIDs.remove(0);
            List<Integer> capIDList = new ArrayList<>();
            CollectionUtils.collect(inputCapIDs, new Transformer() {
                @Override
                public Object transform(Object o) {
                    return Integer.valueOf(o.toString());
                }
            }, capIDList);
            List<Product> capList = productMapper.selectByIDList(capIDList);

            List<UserFeedBackInfo> adopted = userFeedBackInfoMapper.selectByEventNode(bpID, 4, 2);
            List<Integer> adoptedList = new ArrayList<>();
            for (UserFeedBackInfo fd : adopted) {
                adoptedList.add(fd.getItemID());
            }
            List<UserFeedBackInfo> unrelated = userFeedBackInfoMapper.selectByEventNode(bpID, 4, 3);
            List<Integer> unrelatedList = new ArrayList<>();
            for (UserFeedBackInfo fd : unrelated) {
                unrelatedList.add(fd.getItemID());
            }
            Map<String, Object> resultMap = new HashMap();
            resultMap.put("cerementList", cerementList);
            resultMap.put("capList", capList);
            resultMap.put("adoptedList", adoptedList);
            resultMap.put("unrelatedList", unrelatedList);
            resultMap.put("prefix", FileHandler.TREAL_STORE_PREFIX);
            return JsonHandler.writeJsontoResponse(7000, resultMap);
        } catch (JSONException e) {
            e.printStackTrace();
            LogRecord.ERROR.error(e.toString());
            return JsonHandler.writeJsontoResponse(7003, "");
        } catch (Exception e) {
            e.printStackTrace();
            LogRecord.ERROR.error(e.toString());
            return JsonHandler.writeJsontoResponse(7001, "");
        }
    }


    /**
     * 推荐花圈、挽联、胸花（展示在遗体告别旁，流程状态 < 6 时使用）
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "/recWreaths", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> recWreaths(HttpServletRequest request) {
        try {
            String jsonStr = JsonHandler.readJsonFromRequest(request);
            JSONObject obj = JSONObject.fromObject(jsonStr);
            Map<String,Object> isLogin = OAuthHandler.ApiValidateUserLogin(obj);
            if(isLogin.containsKey("errorcode"))
                return JsonHandler.writeJsontoResponse((int)isLogin.get("errorcode"), "");
            int bpID = obj.getInt("bpID");
            BusiProcBaseInfo bpInfo = bpBaseInfoMapper.selectByPrimaryKey(bpID);
            //在冷启动情况下，根据逝者属性获取相似逝者情况
            List<String> inputDeadIDs = Arrays.asList(bpInfo.getSimilarDeadInfoIDs().split(" "));
            List<Integer> deadIDList = new ArrayList<>();
            CollectionUtils.collect(inputDeadIDs, new Transformer() {
                @Override
                public Object transform(Object o) {
                    return Integer.valueOf(o.toString());
                }
            }, deadIDList);

            Map<String, Object> resultMap = new HashMap<>();
            //获取这些用户购买过的花圈、挽联、胸花
            List<Integer> proTypeList = new ArrayList<>();
            List<Product> wreathList = null;
            List<Product> coupletList = null;
            List<Product> flowerList = null;
            proTypeList.add(25);
            List<Integer> wreathIDList = buyRecordMapper.selectByDeadIDItemType(deadIDList, proTypeList);//花圈
            if (wreathIDList != null && wreathIDList.size() != 0) {
                wreathList = productMapper.selectByIDList(wreathIDList);
            }
            proTypeList.clear();
            proTypeList.add(26);
            List<Integer> coupletIDList = buyRecordMapper.selectByDeadIDItemType(deadIDList, proTypeList);//挽联
            if (coupletIDList != null && coupletIDList.size() != 0) {
                coupletList = productMapper.selectByIDList(coupletIDList);
            }
            proTypeList.clear();
            proTypeList.add(53);
            List<Integer> flowerIDList = buyRecordMapper.selectByDeadIDItemType(deadIDList, proTypeList);//胸花
            if (flowerIDList != null && flowerIDList.size() != 0) {
                flowerList = productMapper.selectByIDList(flowerIDList);
            }
            //TODO 若有用户在其他平台行为沉淀，用协同过滤

            resultMap.put("wreathList", wreathList.subList(0,wreathList.size() > 4 ? 4 : wreathList.size()));
            resultMap.put("coupletList", coupletList.subList(0,coupletList.size() > 3 ? 3 : coupletList.size()));
            resultMap.put("otherList", flowerList == null ? null : flowerList.subList(0,flowerList.size() > 1 ? 1 : flowerList.size()));
            resultMap.put("prefix", FileHandler.TREAL_STORE_PREFIX);

            //保存返回结果
            StringBuilder result = new StringBuilder();
            result.append("wreathList ");
            for (Product o : wreathList.subList(0,wreathList.size() > 4 ? 4 : wreathList.size())) {
                result.append(o.getId()).append(" ");
            }
            result.append("!coupletList ");
            for (Product o : coupletList.subList(0,coupletList.size() > 3 ? 3 : coupletList.size())) {
                result.append(o.getId()).append(" ");
            }
            result.append("!otherList ");
            if(flowerList != null) {
            	for (Product o : flowerList) {
                    result.append(o.getId()).append(" ");
                }
            }
            RecResult recResult = recResultMapper.selectByEventNode(bpID, 5);
            if (recResult == null) {
                recResult = new RecResult();
                recResult.setBpID(bpID);
                recResult.setItemType(5);//5：花圈、挽联、胸花
                recResult.setItemIDs(result.toString());
                recResult.setState(1);
                recResult.setAddTime(new Date());
                recResultMapper.insertSelective(recResult);
            } else {
                recResult.setItemIDs(result.toString());
                recResult.setState(1);
                recResult.setAddTime(new Date());
                recResultMapper.updateByPrimaryKeySelective(recResult);
            }
            return JsonHandler.writeJsontoResponse(7000, resultMap);
        } catch (JSONException e) {
            e.printStackTrace();
            LogRecord.ERROR.error(e.toString());
            return JsonHandler.writeJsontoResponse(7003, "");
        } catch (Exception e) {
            e.printStackTrace();
            LogRecord.ERROR.error(e.toString());
            return JsonHandler.writeJsontoResponse(7001, "");
        }
    }


    /**
     * 获取推荐花圈、挽联、陪葬品结果（流程状态 >= 6 时 使用）
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "/getRecWreaths", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> getRecWreaths(HttpServletRequest request) {
        try {
            String jsonStr = JsonHandler.readJsonFromRequest(request);
            JSONObject obj = JSONObject.fromObject(jsonStr);
            Map<String, Object> isLogin = OAuthHandler.ApiValidateUserLogin(obj);
            if (isLogin.containsKey("errorcode"))
                return JsonHandler.writeJsontoResponse((int) isLogin.get("errorcode"), "");
            int bpID = obj.getInt("bpID");
            int itemType = obj.getInt("itemType");
            String result = recResultMapper.selectByEventNode(bpID, itemType).getItemIDs();
            String[] kinds = result.split("!");
            List<String> inputWreathIDs = new ArrayList<>(Arrays.asList(kinds[0].split(" ")));
            inputWreathIDs.remove(0);
            List<Integer> wreathIDList = new ArrayList<>();
            CollectionUtils.collect(inputWreathIDs, new Transformer() {
                @Override
                public Object transform(Object o) {
                    return Integer.valueOf(o.toString());
                }
            }, wreathIDList);
            List<Product> wreathList = productMapper.selectByIDList(wreathIDList);

            List<String> inputCoupletIDs = new ArrayList<>(Arrays.asList(kinds[1].split(" ")));
            inputCoupletIDs.remove(0);
            List<Integer> coupletIDList = new ArrayList<>();
            CollectionUtils.collect(inputCoupletIDs, new Transformer() {
                @Override
                public Object transform(Object o) {
                    return Integer.valueOf(o.toString());
                }
            }, coupletIDList);
            List<Product> coupletList = productMapper.selectByIDList(coupletIDList);

            List<String> inputOtherIDs = new ArrayList<>(Arrays.asList(kinds[2].split(" ")));
            inputOtherIDs.remove(0);
            List<Integer> otherIDList = new ArrayList<>();
            CollectionUtils.collect(inputOtherIDs, new Transformer() {
                @Override
                public Object transform(Object o) {
                    return Integer.valueOf(o.toString());
                }
            }, otherIDList);
            List<Product> otherList = productMapper.selectByIDList(otherIDList);

            List<UserFeedBackInfo> adopted = userFeedBackInfoMapper.selectByEventNode(bpID, 5, 2);
            List<Integer> adoptedList = new ArrayList<>();
            for (UserFeedBackInfo fd : adopted) {
                adoptedList.add(fd.getItemID());
            }
            List<UserFeedBackInfo> unrelated = userFeedBackInfoMapper.selectByEventNode(bpID, 5, 3);
            List<Integer> unrelatedList = new ArrayList<>();
            for (UserFeedBackInfo fd : unrelated) {
                unrelatedList.add(fd.getItemID());
            }
            Map<String, Object> resultMap = new HashMap();
            resultMap.put("wreathList", wreathList);
            resultMap.put("coupletList", coupletList);
            resultMap.put("otherList", otherList);
            resultMap.put("adoptedList", adoptedList);
            resultMap.put("unrelatedList", unrelatedList);
            resultMap.put("prefix", FileHandler.TREAL_STORE_PREFIX);
            return JsonHandler.writeJsontoResponse(7000, resultMap);
        } catch (JSONException e) {
            e.printStackTrace();
            LogRecord.ERROR.error(e.toString());
            return JsonHandler.writeJsontoResponse(7003, "");
        } catch (Exception e) {
            e.printStackTrace();
            LogRecord.ERROR.error(e.toString());
            return JsonHandler.writeJsontoResponse(7001, "");
        }
    }

    /**
     * 推荐骨灰盒（展示在遗体火化旁，流程状态 < 6 时使用）
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "/recCaskets", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> recCaskets(HttpServletRequest request) {
        try {
            String jsonStr = JsonHandler.readJsonFromRequest(request);
            JSONObject obj = JSONObject.fromObject(jsonStr);
            Map<String,Object> isLogin = OAuthHandler.ApiValidateUserLogin(obj);
            if(isLogin.containsKey("errorcode"))
                return JsonHandler.writeJsontoResponse((int)isLogin.get("errorcode"), "");
            int bpID = obj.getInt("bpID");
            BusiProcBaseInfo bpInfo = bpBaseInfoMapper.selectByPrimaryKey(bpID);
            //在冷启动情况下，根据逝者属性获取相似逝者情况
            List<String> inputDeadIDs = Arrays.asList(bpInfo.getSimilarDeadInfoIDs().split(" "));
            List<Integer> deadIDList = new ArrayList<>();
            CollectionUtils.collect(inputDeadIDs, new Transformer() {
                @Override
                public Object transform(Object o) {
                    return Integer.valueOf(o.toString());
                }
            }, deadIDList);
            //获取这些用户购买过的骨灰盒
            List<Integer> casketTypeList = productCatalogueMapper.selectSonCatalogID(9);
            List<Integer> casketIDList = buyRecordMapper.selectByDeadIDItemType(deadIDList, casketTypeList);
            List<Product> caskets = productMapper.selectByIDList(casketIDList);
            //TODO 若有用户在其他平台行为沉淀，用协同过滤

            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("casketList", caskets);
            resultMap.put("prefix", FileHandler.TREAL_STORE_PREFIX);

            //保存返回结果
            StringBuilder result = new StringBuilder();
            result.append("casketList ");
            for (Product o : caskets) {
                result.append(o.getId()).append(" ");
            }
            RecResult recResult = recResultMapper.selectByEventNode(bpID, 6);
            if (recResult == null) {
                recResult = new RecResult();
                recResult.setBpID(bpID);
                recResult.setItemType(6);//6：骨灰盒
                recResult.setItemIDs(result.toString());
                recResult.setState(1);
                recResult.setAddTime(new Date());
                recResultMapper.insertSelective(recResult);
            } else {
                recResult.setItemIDs(result.toString());
                recResult.setState(1);
                recResult.setAddTime(new Date());
                recResultMapper.updateByPrimaryKeySelective(recResult);
            }
            return JsonHandler.writeJsontoResponse(7000, resultMap);
        } catch (JSONException e) {
            e.printStackTrace();
            LogRecord.ERROR.error(e.toString());
            return JsonHandler.writeJsontoResponse(7003, "");
        } catch (Exception e) {
            e.printStackTrace();
            LogRecord.ERROR.error(e.toString());
            return JsonHandler.writeJsontoResponse(7001, "");
        }
    }


    /**
     * 获取骨灰盒推荐结果（流程状态 >= 6 时 使用）
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "/getRecRecCaskets", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> getRecRecCaskets(HttpServletRequest request) {
        try {
            String jsonStr = JsonHandler.readJsonFromRequest(request);
            JSONObject obj = JSONObject.fromObject(jsonStr);
            Map<String, Object> isLogin = OAuthHandler.ApiValidateUserLogin(obj);
            if (isLogin.containsKey("errorcode"))
                return JsonHandler.writeJsontoResponse((int) isLogin.get("errorcode"), "");
            int bpID = obj.getInt("bpID");
            int itemType = obj.getInt("itemType");
            String result = recResultMapper.selectByEventNode(bpID, itemType).getItemIDs();
            List<String> inputCasketIDs = new ArrayList<>(Arrays.asList(result.split(" ")));
            inputCasketIDs.remove(0);
            List<Integer> casketIDList = new ArrayList<>();
            CollectionUtils.collect(inputCasketIDs, new Transformer() {
                @Override
                public Object transform(Object o) {
                    return Integer.valueOf(o.toString());
                }
            }, casketIDList);
            List<Product> casketList = productMapper.selectByIDList(casketIDList);

            List<UserFeedBackInfo> adopted = userFeedBackInfoMapper.selectByEventNode(bpID, 4, 2);
            List<Integer> adoptedList = new ArrayList<>();
            for (UserFeedBackInfo fd : adopted) {
                adoptedList.add(fd.getItemID());
            }
            List<UserFeedBackInfo> unrelated = userFeedBackInfoMapper.selectByEventNode(bpID, 4, 3);
            List<Integer> unrelatedList = new ArrayList<>();
            for (UserFeedBackInfo fd : unrelated) {
                unrelatedList.add(fd.getItemID());
            }
            Map<String, Object> resultMap = new HashMap();
            resultMap.put("casketList", casketList);
            resultMap.put("adoptedList", adoptedList);
            resultMap.put("unrelatedList", unrelatedList);
            resultMap.put("prefix", FileHandler.TREAL_STORE_PREFIX);
            return JsonHandler.writeJsontoResponse(7000, resultMap);
        } catch (JSONException e) {
            e.printStackTrace();
            LogRecord.ERROR.error(e.toString());
            return JsonHandler.writeJsontoResponse(7003, "");
        } catch (Exception e) {
            e.printStackTrace();
            LogRecord.ERROR.error(e.toString());
            return JsonHandler.writeJsontoResponse(7001, "");
        }
    }

    /**
     * 推荐公墓（流程状态 < 8 时 使用）
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "/recCemetery", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> recCemetery(HttpServletRequest request) {
        try {
            String jsonStr = JsonHandler.readJsonFromRequest(request);
            JSONObject obj = JSONObject.fromObject(jsonStr);
            Map<String, Object> isLogin = OAuthHandler.ApiValidateUserLogin(obj);
            if (isLogin.containsKey("errorcode"))
                return JsonHandler.writeJsontoResponse((int) isLogin.get("errorcode"), "");
            User tempU = (User) isLogin.get("user");
            User user = userMapper.selectByPrimaryKey(tempU.getId());
            //根据逝者信息，利用L2R_L2LOSS_SVC模型，预测用户可能选择的安葬类型
            int bpID = obj.getInt("bpID");
            Map<String,Integer> map = new HashMap<>();
            BusiProcBaseInfo bpbi = bpBaseInfoMapper.selectByPrimaryKey(bpID);
            String cPos = user.getIDCard().substring(0, 6);
            map.put("c_PosID", areaCodeMapper.selectByPrimaryKey(cPos).getId());
            String cBirthYear = user.getIDCard().substring(6, 10);
            map.put("c_age", 2018 - Integer.valueOf(cBirthYear));
            map.put("c_sex", (int) user.getIDCard().charAt(16) %2);
            String dPos = bpbi.getDeadIDNumber().substring(0, 6);
            map.put("d_PosID",areaCodeMapper.selectByPrimaryKey(dPos).getId());
            String dBirthYear = bpbi.getDeadIDNumber().substring(6, 10);
            map.put("d_age", 2018 - Integer.valueOf(dBirthYear));
            map.put("d_sex", (int) bpbi.getDeadIDNumber().charAt(16)%2);
            Double prediction  = Predict4Ceme.predict(map, bpbi);
            //获取用户对殡仪馆的选择操作结果
            List<Integer> funeralIDs = getRecFunResult(bpbi);
            //prediction骨灰 寄存(殡仪馆):6  寄存(公墓):1、3  墓葬(公墓):2、4  树葬(陵园):5、12  撒散(殡仪服务机构):7
            //不留灰:8 其他:9 自行安葬:10 出省外运:11
            int burialType;
            int predicType = (prediction).intValue();
            List<Organization> candidateOrgList = new ArrayList<>();
            if(predicType == 6) {//殡仪馆寄存
                burialType = 1;
                Map<String,Object> paraMap = new HashMap<>();
                paraMap.put("orgIDs",funeralIDs);
                candidateOrgList.addAll(organizationMapper.selectByOrgIDs(paraMap));
            } else if (predicType == 5 || predicType == 12){ //树葬 推荐陵园
                burialType = 3;
                candidateOrgList.addAll(getNearByOrgsByType(funeralIDs, CemeteryPark_ORGTYPE_ID,30));
            } else if (predicType == 7) { //撒散 推荐第三方服务机构
                burialType = 4;
                candidateOrgList.addAll(getNearByOrgsByType(funeralIDs, OfferService3_ORGTYPE_ID,30));
            } else { //推荐公墓
                if (predicType == 1 || predicType == 3) //公墓寄存
                    burialType = 1;
                else
                    burialType = 2;
                //获取上面殡仪馆列表中殡仪馆周围的公墓 6个
                candidateOrgList.addAll(getNearByOrgsByType(funeralIDs, Cemetery_ORGTYPE_ID,30));
            }

            //保存返回结果
            StringBuilder result = new StringBuilder();
            result.append("burialType "+ burialType);
            result.append("!candidateOrgList ");
            for (Organization o : candidateOrgList) {
                result.append(o.getId()).append(" ");
            }
            RecResult recResult = recResultMapper.selectByEventNode(bpID, 7);
            if (recResult == null) {
                recResult = new RecResult();
                recResult.setBpID(bpID);
                recResult.setItemType(7);//7：公墓陵园等
                recResult.setItemIDs(result.toString());
                recResult.setState(1);
                recResult.setAddTime(new Date());
                recResultMapper.insertSelective(recResult);
            } else {
                recResult.setItemIDs(result.toString());
                recResult.setState(1);
                recResult.setAddTime(new Date());
                recResultMapper.updateByPrimaryKeySelective(recResult);
            }

//            // 读取根据用户行为使用ItemKNN得到的推荐列表
//            String fileName = "/com/recSys/config/offlineTaskOutput.properties";
//            String inputPath = new FileHandler().readConfig(fileName,"recommendOrgListByItemKNNPath");
//            List<RecommendedItem> recommendedItemList = new FileHandler().readRecommendList(inputPath,user.getId());
//
//            //将推荐列表的殡仪馆添加到候选列表
//            for (RecommendedItem ri:
//                    recommendedItemList) {
//                Organization o = organizationMapper.selectByPrimaryKey(Integer.valueOf(ri.getItemId()));
//                if(o != null)
//                    candidateOrgList.add(o);
//            }
//            GeneralHandler.removeDuplicate(candidateOrgList);
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("burialType",burialType);
            resultMap.put("candidateOrgList", candidateOrgList);
            resultMap.put("prefix", FileHandler.TREAL_STORE_PREFIX);
            return JsonHandler.writeJsontoResponse(7000, resultMap);
        } catch (JSONException e) {
            e.printStackTrace();
            LogRecord.ERROR.error(e.toString());
            return JsonHandler.writeJsontoResponse(7003, "");
        } catch (Exception e) {
            e.printStackTrace();
            LogRecord.ERROR.error(e.toString());
            return JsonHandler.writeJsontoResponse(7001, "");
        }
    }

    /**
     * 获取推荐公墓结果（流程状态 >= 8 时 使用）
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "/getRecCemeteryResult", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> getRecCemeteryResult(HttpServletRequest request) {
        try {
            String jsonStr = JsonHandler.readJsonFromRequest(request);
            JSONObject obj = JSONObject.fromObject(jsonStr);
            Map<String, Object> isLogin = OAuthHandler.ApiValidateUserLogin(obj);
            if (isLogin.containsKey("errorcode"))
                return JsonHandler.writeJsontoResponse((int) isLogin.get("errorcode"), "");
            int bpID = obj.getInt("bpID");
            int itemType = obj.getInt("itemType");
            String result = recResultMapper.selectByEventNode(bpID, itemType).getItemIDs();
            String[] kinds = result.split("!");
            String burialType = kinds[0].split(" ")[1];
            String[] orgIDList = kinds[1].split(" ");
            List<Organization> candidateOrgList = new ArrayList<>();
            for (int i=1; i < orgIDList.length; i++) {
                candidateOrgList.add(organizationMapper.selectByPrimaryKey(Integer.valueOf(orgIDList[i])));
            }
            List<UserFeedBackInfo> adopted = userFeedBackInfoMapper.selectByEventNode(bpID, 7, 2);
            List<Integer> adoptedList = new ArrayList<>();
            for (UserFeedBackInfo fd : adopted) {
                adoptedList.add(fd.getItemID());
            }
            List<UserFeedBackInfo> unrelated = userFeedBackInfoMapper.selectByEventNode(bpID, 7, 3);
            List<Integer> unrelatedList = new ArrayList<>();
            for (UserFeedBackInfo fd : unrelated) {
                unrelatedList.add(fd.getItemID());
            }
            Map<String, Object> resultMap = new HashMap();
            resultMap.put("candidateOrgList", candidateOrgList);
            resultMap.put("burialType", burialType);
            resultMap.put("adoptedList", adoptedList);
            resultMap.put("unrelatedList", unrelatedList);
            resultMap.put("prefix", FileHandler.TREAL_STORE_PREFIX);
            return JsonHandler.writeJsontoResponse(7000, resultMap);
        } catch (JSONException e) {
            e.printStackTrace();
            LogRecord.ERROR.error(e.toString());
            return JsonHandler.writeJsontoResponse(7003, "");
        } catch (Exception e) {
            e.printStackTrace();
            LogRecord.ERROR.error(e.toString());
            return JsonHandler.writeJsontoResponse(7001, "");
        }
    }

    /**
     * 获取某地点一定范围内的某类机构 按距离排序
     *
     * @param longitude 经度
     * @param latitude  纬度
     * @param orgType   机构类型
     * @param dis       距离（km）
     */
    private List<Organization> searchNearbyOrgs(double longitude, double latitude, int orgType, double dis) {
        if (Math.abs(latitude) > 1e-8 && Math.abs(longitude) > 1e-8) {
            double[] dll = GeneralHandler.getAreaPoint(longitude, latitude, dis);
            Map<String, Object> paraMap = new HashMap<>();
            paraMap.put("minlat", latitude - dll[1]);
            paraMap.put("maxlat", latitude + dll[1]);
            paraMap.put("minlng", longitude - dll[0]);
            paraMap.put("maxlng", longitude + dll[0]);
            paraMap.put("orgType", orgType);
            List<Organization> initial = organizationMapper.selectByArea(paraMap);
            //根据距离排序
            if (initial.size() > 2) {
                TreeMap<Double, Organization> disMap = new TreeMap<>();
                for (Organization o : initial) {
                    Double distance = GeneralHandler.distance(longitude, latitude, o.getLongitude(), o.getLatitude());
                    disMap.put(distance, o);
                }
                initial.clear();
                for (Map.Entry<Double, Organization> entry : disMap.entrySet()) {
                    initial.add(entry.getValue());
                }
            }
            return initial;
        }
        return null;
    }

    /**
     * 获取某机构列表周围的某类机构
     * @param orgIDs
     * @param targetType
     * @param dis
     * @return
     */
    private List<Organization> getNearByOrgsByType(List<Integer> orgIDs, int targetType, int dis) {
        List<Organization> targetOrgList = new ArrayList<>();
        for (Integer orgID : orgIDs) {
            Organization o = organizationMapper.selectByPrimaryKey(orgID);
            double lng = o.getLongitude();
            double lat = o.getLatitude();
            List<Organization> nearByList = searchNearbyOrgs(lng, lat, targetType, dis);
            if (nearByList != null) {
                for (Organization org : nearByList) {
                    if (!targetOrgList.contains(org) && targetOrgList.size() < 6)
                        targetOrgList.add(org);
                }
            }
        }
        return  targetOrgList;
    }

    /**
     * 获取当前状态下 用户对殡仪馆的选择结果（每个结点都做考虑） 若无选择 则返回原始推荐结果
     * @param bpbi
     * @return
     */
    private List<Integer> getRecFunResult(BusiProcBaseInfo bpbi) {
        List<Integer> funeralIDs = new ArrayList<>();
        if (bpbi.getState() >= 3) {//用户已对殡仪馆选择完成
            //用户对推荐殡仪馆结果的反馈(采纳)
            List<UserFeedBackInfo> fdInfos = userFeedBackInfoMapper.selectByEventNode(bpbi.getID(), 1, 2);
            if (fdInfos != null && fdInfos.size() != 0) {
                for (UserFeedBackInfo fd : fdInfos) {
                    funeralIDs.add(fd.getItemID());
                }
            } else if (funeralIDs.size() == 0 && bpbi.getState() >= 4) { //遗体接送服务选择完成
                //查看反馈结果中 服务提供方的殡仪馆 即为用户选定的殡仪馆
                List<UserFeedBackInfo> fdInfos2 = new ArrayList<>();
                fdInfos2.addAll(userFeedBackInfoMapper.selectByEventNode(bpbi.getID(), 2, 2));
                if(fdInfos2.size() == 0 && bpbi.getState() >= 6) { //遗体寄存服务选择完成
                    //查看反馈结果中 服务提供方的殡仪馆 即为用户选定的殡仪馆
                    fdInfos2.addAll(userFeedBackInfoMapper.selectByEventNode(bpbi.getID(), 3, 2));
                }
                for (UserFeedBackInfo fd : fdInfos2) {
                    int servID = fd.getItemID();
                    ServiceInfo s = serviceMapper.selectByID(servID);
                    Organization o = organizationMapper.selectByPrimaryKey(s.getOrgID());
                    if (o.getOrgType() == FuneralParlor_ORGTYPE_ID) funeralIDs.add(o.getId());
                }
            }
            if (funeralIDs.size() == 0) {//用户对推荐殡仪馆结果的反馈(查看)
                List<UserFeedBackInfo> fdInfos1 = userFeedBackInfoMapper.selectByEventNode(bpbi.getID(), 1, 1);
                if (fdInfos1 != null && fdInfos1.size() != 0) {
                    for (UserFeedBackInfo fd : fdInfos1) {
                        funeralIDs.add(fd.getItemID());
                    }
                }
            }
            //TODO 用户在其他平台行为沉淀
        }
        if (funeralIDs.size() == 0) {// 没有用户反馈时，获取殡仪馆推荐结果列表
            String result = recResultMapper.selectByEventNode(bpbi.getID(), 1).getItemIDs();
            String[] orgIDList = result.split(" ");
            for (String orgID : orgIDList) {
                funeralIDs.add(Integer.valueOf(orgID));
            }
        }
        return funeralIDs;
    }
}
